import Bezier from "./bezier";

export function drawPath(ctx, points, style, callback, debug) {
    if (points.length == 2) {
        ctx.beginPath();
        ctx.moveTo(points[0][0], points[0][1]);
        ctx.lineTo(points[1][0], points[1][1]);
        ctx.stroke();
        ctx.closePath();
    } else if (points.length >= 3) {
        const list = parse(points, style, debug ? ctx : undefined);
        for (let i of list) {
            i.draw(ctx, debug);
        }
    }
}

export function parse(points, style, ctx) {
    if (points.length < 3) {
        return [];
    }

    const len = points.length,
        bezierList = [];
    let [c2, c1] = getControl(points[0], points[0], points[1], ctx),
        c3 = null;

    for (let i = 0; i <= len - 3; i++) {
        [c2, c3] = getControl(points[i], points[i + 1], points[i + 2], ctx);
        bezierList.push(new Bezier(points[i], c1, c2, points[i + 1], style));
        c1 = c3;
    }
    [c2, c3] = getControl(points[len - 2], points[len - 1], points[len - 1], ctx);
    bezierList.push(new Bezier(points[len - 2], c1, c2, points[len - 1], style));

    return bezierList;
}

function getControl(a, b, c, ctx) {
    let m1 = mid(a, b), m2 = mid(b, c);
    const ab = dis(a, b);
    const r = ab / (dis(b, c) + ab);
    const p = mid(m1, m2, r);
    const pb = [b[0] - p[0], b[1] - p[1]];
    m1 = [m1[0] + pb[0], m1[1] + pb[1]];
    m2 = [m2[0] + pb[0], m2[1] + pb[1]];

    if (ctx) {
        ctx.fillStyle = "#ff0000";
        drawPoint(ctx, m1, 2);
        drawPoint(ctx, m2, 2);
        ctx.strokeStyle = "#ff00ff";
        drawLine(ctx, m1, m2);
    }
    return [m1, m2];
}

function mid(a, b, r = 0.5) {
    return [(b[0] - a[0]) * r + a[0], (b[1] - a[1]) * r + a[1]];
}

function dis(a, b) {
    return Math.sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]));
}


function drawPoint(ctx, p, size) {
    ctx.beginPath();
    ctx.arc(p[0], p[1], size, 0, Math.PI * 2);
    ctx.fill();
    ctx.closePath();
}

function drawLine(ctx, p1, p2) {
    ctx.beginPath();
    ctx.moveTo(p1[0], p1[1]);
    ctx.lineTo(p2[0], p2[1]);
    ctx.stroke();
    ctx.closePath();
}